package no.uio.ifi.cop.cl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;

/**
 * A Conjunction holds a list of Predicates.
 *
 * A Conjunction has a type which identifies speacial types
 * of formulas, empty left or right hand sides of implications
 * holds CONSTANT's (true/false/goal), or else a plain list
 * of Terms are held by a formula.
 *
 * @version 1.0
 * @author bjarneh@ifi.uio.no
 */


public class Conjunction extends Formula implements Iterable<Term>, Cloneable{

    ArrayList<Term> elements;

    public Conjunction(){
        super();
        elements = new ArrayList<Term>(12);
    }

    public void classify(){
        // the only way you can have a CONSTANT here is if
        // it is a 'true' token, i.e., if first term is a
        // CONSTANT elements.size() == 1 and we have a fact-rule
        if( elements.get(0).isConstant() ){
            this.type = Formula.CONSTANT;
        }else{
            this.type = Formula.CONJUNCTION;
        }
    }

    public void add(Term t){
        elements.add(t);
    }

    public void gatherVariables(Set<String> set){
        for( Term term : elements ){
            term.gatherVariables(set);
        }
    }

    public Iterator<Term> iterator(){
        return elements.iterator();
    }

    public int length(){
        return elements.size();
    }

    public String toString(){
        StringBuilder sb = new StringBuilder();
        int max = elements.size() - 1;
        for(int i = 0; i < max; i++){
            sb.append( elements.get(i).toString() ).append(", ");
        }
        sb.append(elements.get(max).toString());
        return sb.toString();
    }

    public Conjunction clone(){
        Conjunction conjunction = new Conjunction();
        for( Term t : this ){
            conjunction.add( t );
        }
        return conjunction;
    }

    public Conjunction apply(Substitution subst){
        for( Term t : this ){
            t.apply( subst );
        }
        return this;
    }
}

